<?php
/**
 * Unity PC 端素材制作软件 查询整体妆容素材
 *
 * Author: Zeon
 * Date: 2018/4/2
 * Created by Panxsoft.
 */

namespace App\Http\Controllers\PC\CustomerStore;

use App\Http\Controllers\ApiController;
use App\Http\Requests\PC\CustomerStore\Pack\PackStoreRequest;
use App\Http\Requests\PC\CustomerStore\Pack\PackUpdateRequest;
use App\Http\Requests\PC\PackIndexRequest;
use App\Models\Customer\Asset;
use App\Models\Customer\PackAssetPivotProduct;
use App\Models\Panx\Product;
use App\Models\Store\Pack;
use App\Models\Store\PackCategory;
use App\Services\Repositories\Pack\PackRepository;
use App\Services\Utils\Transaction;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Http\Request;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Facades\DB;

class PackController extends ApiController
{
    const ROUTES = [
        'index'   => 'pc.customer.store.pack.index',
        'store'   => 'pc.customer.store.pack.store',
        'update'  => 'pc.customer.store.pack.update',
        'destroy' => 'pc.customer.store.pack.destroy',
    ];

    /**
     * 显示/查询所有panx素材
     *
     * @param PackIndexRequest $request
     *
     * @param $customer_id
     * @param $store_id
     * @return \Illuminate\Http\Response
     */
    public function index(PackIndexRequest $request, int $customer_id, int $store_id)
    {
        /** @var LengthAwarePaginator $packs */
        $packs = (new Pack)
            ->where(compact('customer_id', 'store_id'))
            ->filterPackCategoryId($request->pack_category_id)
            ->latest()
            ->with([
                'assets.products.thumbImage', 'assets.assetPivotProducts.thumbImage'
            ])
            ->paginate($request->per_page ?: 15);

        /** @var Collection $pack_collect */
        $pack_collect = $packs->getCollection();

        $this->transformPackProducts($pack_collect);

        return $this->response(compact('packs'));
    }

    /**
     *
     * @param Collection $products
     * @return $this|Collection
     */
    private function transformProducts(Collection $products)
    {
        return $products->transform(function (Product $product) {
            $product->append(['thumb_url']);

            $product->addHidden(['thumbImage']);

            return $product;
        });
    }

    /**
     * @param int $customer_id
     * @param int $store_id
     * @return array|\Illuminate\Http\Response
     */
    public function create(int $customer_id, int $store_id)
    {
        $assets = (new Asset)
            ->where(compact('customer_id', 'store_id'))
            ->get();
        $pack_categories = PackCategory::where('customer_id', $customer_id)
            ->get();

        return $this->response(compact('assets', 'pack_categories'));
    }

    /**
     * @test
     *
     * @param PackStoreRequest $request
     * @param int $customer_id
     * @param int $store_id
     * @return array|\Illuminate\Http\Response
     * @throws \Exception
     */
    public function store(PackStoreRequest $request, int $customer_id, int $store_id)
    {
        $pack_data = $this->assemblePackStoreData($request, $customer_id, $store_id);

        $stored = Transaction::handle(function () use ($pack_data) {
            /** @var Pack $pack */
            $pack = (new Pack)->create($pack_data['pack']);

            $pack->assets()->sync($pack_data['sync_assets']);

            $this->savePackPivotAssetProduct($pack_data['assets'], $pack);

            return $pack;
        });

        return $this->response(compact('stored'));
    }

    
    /**
     * @param array $asset_data
     * @param Pack $pack
     * @return bool
     */
    private function savePackPivotAssetProduct(array $asset_data, Pack $pack)
    {
        $sync_data = [];

        $pack_id = $pack->id;

        foreach ($asset_data as $asset) {
            if ( isset( $asset['product_ids'] ) )
            {
                foreach ($asset['product_ids'] as $pid) {
                    $sync_data [] = [
                        'pack_id'    => $pack->id,
                        'asset_id'   => $asset['asset_id'],
                        'product_id' => $pid,
                    ];
                }
            }
        }

        // 更新，先执行删除
        DB::table('pack_asset_pivot_product')->where('pack_id', $pack_id)->delete();

        DB::table('pack_asset_pivot_product')->insert($sync_data);

        return true;
    }


    /**
     * @test
     *
     * @param PackUpdateRequest $request
     * @param int $customer_id
     * @param int $store_id
     * @param $pack_id
     * @return array|\Illuminate\Http\Response
     * @throws \Exception
     */
    public function update(PackUpdateRequest $request, int $customer_id, int $store_id, $pack_id)
    {
        /** @var Pack $pack */
        $pack = (new Pack)
            ->where(compact($customer_id, $store_id))
            ->find($pack_id);
        $this->checkItemExist($pack, trans('pc.pack'));

        $pack_data = $this->assemblePackStoreData($request, $customer_id, $store_id);

        $updated = Transaction::handle(function () use ($pack, $pack_data) {
            $pack->update($pack_data['pack']);

            $pack->assets()->sync($pack_data['sync_assets']);

            $this->savePackPivotAssetProduct($pack_data['assets'], $pack);

            return $pack;
        });

        return $this->response(compact('updated'));
    }

    /**
     * @param int $customer_id
     * @param int $store_id
     * @param $pack_id
     * @return array|\Illuminate\Http\Response
     * @throws \Exception
     */
    public function destroy(int $customer_id, int $store_id, $pack_id)
    {
        /** @var Pack $pack */
        $pack = (new Pack)
            ->where(compact($customer_id, $store_id))
            ->find($pack_id);
        $this->checkItemExist($pack, trans('pc.pack'));

        $deleted = PackRepository::deletePack($pack);

        return $this->response(compact('deleted'));
    }

    /**
     * @param PackStoreRequest|PackUpdateRequest|Request $request
     * @param int $customer_id
     * @param int $store_id
     * @return array
     */
    private function assemblePackStoreData(Request $request, int $customer_id, int $store_id): array
    {
        $store_data = [];

        $store_data['pack'] = [
            'thumb'            => $request->thumb ?: '', // db column not null
            'name'             => $request->name,
            'priority'         => $request->priority ?? 0,
            'customer_id'      => $customer_id,
            'store_id'         => $store_id,
            'pack_category_id' => $request->pack_category_id ?? 0,
        ];

        $store_data['sync_assets'] = $this->assembleSyncAssets($request->assets);
//        $store_data['sync_pack_pivot_asset'] = $this->savePackPivotAssetProduct($request->assets);

        $store_data['assets'] = $request->assets;

        return $store_data;
    }

    /**
     * @param array $assets
     * @return array
     */
    private function assembleSyncAssets(array $assets): array
    {
        return collect($assets)
            ->mapWithKeys(function (array $asset) {
                return [
                    $asset['asset_id'] => [
                        'index' => $asset['index'],
                    ],
                ];
            })
            ->all();
    }

    /**
     * @param $packs
     */
    private function transformPackProducts(Collection $packs): void
    {
        $packs->each(function (Pack $pack) {
            $pack->assets->each(function (Asset $asset) use ($pack) {

                $asset->pivot_products = $this->transformProducts(
                    $asset->packAssetPivotProducts($pack->id)
                );

                $asset->addHidden(['products', 'assetPivotProducts']);
            });
        });
    }

}
